home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / simcode.arc / UPDOWN.PAS < prev    next >
Pascal/Delphi Source File  |  1985-01-19  |  22KB  |  868 lines

  1. {$symtab-,$pagesize:85,$linesize:96,$debug-,
  2. $title:'UPDOWN.PAS -- Send files back and forth'}
  3. {    COPYRIGHT @ 1982
  4.     Jim Holtman and Eric Holtman
  5.     35 Dogwood Trail
  6.     Randolph, NJ 07869
  7.     (201) 361-3395
  8. }
  9. {$include:'stdio.inc'}
  10. {$list-}
  11. {$include:'filkqq.inc'}
  12. {$list+,Included 'filkqq.inc'}
  13.  
  14.  module updown;
  15.  
  16.      uses
  17.      filkqq,stdio;
  18. {$include:'simterm.inc'}
  19. {$include:'graph.inc'}
  20. {$include:'comm.inc'}
  21.  
  22.      const
  23.          Ctrl_X = chr(#18);
  24.  
  25.      var
  26.      display_buffer_addr [external] : word;
  27.      total_errors : integer;
  28.  
  29.      procedure ck(a : integer;
  30.          const b : string);
  31.  
  32.      external;
  33.  
  34.      function getc(flag : LOOP_FLAG) : integer;
  35.  
  36.      external;
  37.  
  38.      procedure putchar(inchar : char);
  39.  
  40.      external;
  41.  
  42.      procedure savescreen;
  43.  
  44.      external;
  45.  
  46.      procedure restorescreen;
  47.  
  48.      external;
  49.  
  50.      function com_get(var inch : char) : boolean;
  51.  
  52.      external;
  53.  
  54.      function x_cont(new : boolean) : boolean;
  55.  
  56.      external;
  57.  
  58.      procedure net_pack(source,dest : adrmem;
  59.          size : word);
  60.  
  61.      external;
  62.  
  63.      procedure net_unpack(source,dest : adrmem;
  64.          size : word);
  65.  
  66.      external;
  67.  
  68.      procedure clear_to_bot;
  69.  
  70.      var
  71.          i,x,y : integer;
  72.  
  73.      begin               {clear display}
  74.          xrcurp(x,y);
  75.          xwca(NULLB,(RIGHT_MAR+1)-x);
  76.          for i := y+1 to BOTTOM do begin
  77.          xxmove(LEFT_MAR,i);
  78.          xwca(NULLB,(RIGHT_MAR+1))   end;
  79.          xxmove(x,y);
  80.          end;
  81.      
  82.      procedure cursor_on;
  83.      begin
  84.         if display_buffer_addr = #B800 then
  85.            xscurt(byword(6,7))    {color graphics}
  86.         else
  87.            xscurt(byword(11,12));    {monochrome}
  88.         end;
  89.  
  90.      procedure cursor_off;
  91.      begin
  92.         cursor_on;    {make sure it is ON corectly}
  93.         xscurt(byword(14,14));  {then turn it OFF}
  94.         end;
  95.  
  96.      procedure disp_data(b,e : integer);
  97.  
  98.      begin
  99.          if e>0 then total_errors := total_errors+1;
  100.          xxmove(0,2);
  101.          writeln('Last Acknowledged Block: ',b);
  102.          writeln('Errors: ', e,'/',total_errors);
  103.          clear_to_bot;
  104.          end;
  105.  
  106.      procedure print_counter(count : word);
  107.  
  108.      var
  109.          outstr : lstring(20);
  110.  
  111.      begin
  112.          if count = 0 then begin
  113.          xxmove(0,10);
  114.          xttywrt('Any key will terminate transfer',7);
  115.          xxmove(0,12);
  116.          xttywrt('# of bytes transferred -',7);
  117.          end
  118.          else begin
  119.          xxmove(24,12);
  120.          eval(encode(outstr,count));
  121.          xttywrt(outstr,#70);
  122.                    {reverse video}
  123.          end;
  124.          end;
  125.  
  126.      procedure parse_file(var infile : lstring) [public];
  127.  
  128.      var
  129.          dir : lstring(100);
  130.          index,str_len : integer;
  131.  
  132.      begin
  133.          str_len := ord(infile.len);
  134.          index := scaneq(-str_len,'\',infile,str_len);
  135.          if index+str_len <> 0 then begin
  136.          copylst(infile,dir);
  137.          delete(dir,index+str_len,1-index);
  138.          delete(infile,1,index+str_len);
  139.          if c_chdir(dir) < 0 then writeln(output,'Directory ',dir,
  140.              ' not found.');
  141.          end;
  142.          end;
  143.  
  144.      procedure down_load_remote(const fn : lstring) [public];
  145.  
  146.      const
  147.          LF = 10;           {line feed}
  148.          BELL_EOF = 7;       {A 'bell' signifies the end-of-file}
  149.          TEXT_EOF = 26;       {Text end of file character}
  150.          PRINT_LIMIT = #f;       {output byte count every 16th character}
  151.  
  152.      var
  153.          ibmfile : file of char;
  154.          infile, outfile : lstring(100);
  155.          cmd_str : lstring(255);
  156.          inchar : integer;
  157.          char_count : word;
  158.          inkey : char;
  159.          bypass_flag : boolean;
  160.  
  161.      begin
  162.          bypass_flag := false;
  163.          savescreen;
  164.          xxcls;
  165.          xxmove(0,0);
  166.          writeln(output,'TEXT file DOWNLOAD (UNIX -> PC)');
  167.          write(output,'From UNIX file: ');
  168.          if (fn.len = 0) then readln(input,infile)
  169.          else begin
  170.          copylst(fn, infile);
  171.          writeln(infile);
  172.          end;
  173.          write(output,'To IBM file (RETURN only to use same name): ');
  174.          if (fn.len = 0) then readln(input,outfile)
  175.          else begin
  176.          copylst(fn, outfile);
  177.          writeln(outfile);
  178.          end;
  179.          parse_file(outfile);  {if no output file specified, use the input
  180.                       file name}
  181.          if outfile.len = 0 then outfile := infile;
  182.          assign(ibmfile,outfile);
  183.          ibmfile.trap := true;
  184.          rewrite(ibmfile);
  185.          if ibmfile.errs <> 0 then begin
  186.          writeln(output,chr(7)*'File not found.'*chr(7));
  187.          sleep(2);
  188.          return;
  189.          end;
  190.          if (fn.len = 0) then begin
  191.          cmd_str := null;
  192.          concat(cmd_str,'cat ');
  193.          concat(cmd_str,infile);
  194.          concat(cmd_str,'; echo '*chr(7)*chr(10));
  195.          send(cmd_str);
  196.          repeat
  197.              inchar := getc(HANG);
  198.              until inchar = LF;
  199.          end;
  200.          char_count := 0;
  201.          cursor_off;
  202.          print_counter(0);       {print the header line}
  203.          repeat
  204. {$mathck-}
  205.          inchar := getc(HANG);
  206.          if inchar = BELL_EOF then ibmfile^ := chr(TEXT_EOF)
  207.          else ibmfile^ := chr(inchar);
  208.          put(ibmfile);
  209.          char_count := char_count + 1;
  210.          if (char_count and #f) = 0 then print_counter(char_count);
  211.          if xxinkey(inkey) <> 0 then begin
  212.                    {terminate transmission}
  213.              eval(breaker);{send interrupt}
  214.              bypass_flag := true;
  215.              end;
  216. {$mathck+}
  217.          until (inchar = BELL_EOF) or (bypass_flag);
  218.          repeat           {eat the final line feed}
  219.          inchar := getc(HANG)
  220.          until (inchar = LF) or bypass_flag;
  221.          cursor_on;
  222.          close(ibmfile);
  223.          restorescreen;
  224.          writeln(output,chr(7)*chr(10)*chr(13)*
  225.              '  **download complete. bytes transferred=',char_count);
  226.          end;
  227.  
  228.      procedure down_load;
  229.  
  230.      var
  231.          l : lstring(2);
  232.  
  233.      begin
  234.          l.len := 0;
  235.          down_load_remote(l);
  236.          end;
  237.  
  238.      procedure up_load_remote(const fn : lstring) [public];
  239.  
  240.      const
  241.          LF = chr(10);
  242.          TEXT_EOF = chr(26);
  243.  
  244.      var
  245.          ibmfile : file of char;
  246.          infile, outfile : lstring(100);
  247.          cmd_str : lstring(255);
  248.          no_of_LFs : integer;
  249.          inchar : char;
  250.          char_count : word;
  251.          wait_flag : boolean;
  252.          i : integer;
  253.          inkey : char;
  254.          bypass_flag : boolean;
  255.  
  256.      begin
  257.          bypass_flag := false;
  258.          savescreen;
  259.          xxcls;
  260.          xxmove(0,0);
  261.          writeln(output,'TEXT file UPLOAD (PC -> UNIX)');
  262.          write(output,'From IBM file: ');
  263.          if (fn.len = 0) then begin
  264.          readln(input,infile);
  265.          end
  266.          else begin
  267.          copylst(fn, infile);
  268.          writeln(infile);
  269.          end;
  270.          parse_file(infile);
  271.          write(output,'To UNIX file (RETURN only to use same name): ');
  272.          if (fn.len = 0) then begin
  273.          readln(input,outfile);
  274.                    {If the output file is not specified, use the
  275.                       input file as default}
  276.          if outfile.len = 0 then begin
  277.              outfile := infile;
  278.              i := positn(':',outfile,1);
  279.                    {delete unit specification if present}
  280.              if i > 0 then delete(outfile,1,i);
  281.              end;
  282.          end
  283.          else begin
  284.          copylst(fn, outfile);
  285.          writeln(outfile);
  286.          end;
  287.          assign(ibmfile,infile);
  288.          ibmfile.trap := true; {allow catching of errors}
  289.          reset(ibmfile);
  290.          if ibmfile.errs <> 0 then begin
  291.          writeln(chr(7)*'****** File Not Found on Disk:',infile);
  292.          sleep(2);
  293.          restorescreen;
  294.          return;
  295.          end;
  296.          cmd_str := null;
  297. {The 'echo' after 'stty -echo' generates a LF so that the program
  298.      will look for 2 LFs before starting the Upload; this prevents
  299.      the first couple of characters from being echoed}
  300.          concat(cmd_str,'stty -echo;echo x;cat >');
  301.          concat(cmd_str,outfile);
  302.          concat(cmd_str,';stty echo'*chr(10));
  303.                    {put on RETURN}
  304.          char_count := 0;
  305.          cursor_off;
  306.          print_counter(0);       {print header}
  307.          if (fn.len = 0) then begin
  308.          send(cmd_str);
  309.          for no_of_LFs := 1 to 2 do
  310.                    {make sure 'stty -echo' is set}
  311.              repeat       {'eat' command echo}
  312.              inchar := chr(getc(HANG))
  313.              until inchar = LF   ;
  314.          end;           {Now copy the file over to UNIX}
  315.          while not eof(ibmfile) do begin
  316.          inchar := ibmfile^;
  317.          case inchar of
  318.              LF: ;       {ignore}
  319.  
  320.              TEXT_EOF:       {encountered text eof, exit}
  321.                  break;
  322.  
  323.              otherwise
  324.              begin
  325. {$mathck-}
  326.                  send(inchar);
  327.                  char_count := char_count+1;
  328.                  if (char_count and #f) = 0 then print_counter(
  329.                      char_count);
  330. {$mathck+}
  331.                  end;
  332.              end;
  333.          if xxinkey(inkey) <> 0 then begin
  334.              send(chr(13));    {output line terminator}
  335.              break;
  336.              end;
  337.          get(ibmfile);
  338.          end;
  339.          if (fn.len = 0) then begin
  340.          send(chr(4));    {send ^D}
  341.          end
  342.          else begin
  343.          send(chr(26)*chr(13)); {send ^Z}
  344.          end;
  345.          cursor_on;
  346.          close(ibmfile);
  347.          restorescreen;
  348.          if (fn.len = 0 ) then writeln(output,chr(7)*chr(10)*chr(13)*
  349.              '  **upload complete. bytes transferred =',char_count);
  350.          end;
  351.  
  352.      procedure up_load;
  353.  
  354.      var
  355.          l : lstring(2);
  356.  
  357.      begin
  358.          l.len := 0;
  359.          up_load_remote(l);
  360.          end;
  361.  
  362.      procedure dump_file;
  363.  
  364.      label
  365.          10;
  366.  
  367.      const
  368.          TEXT_EOF = chr(26);
  369.  
  370.      var
  371.          ibmfile : file of char;
  372.          infile : lstring(100);
  373.          inchar : char;
  374.          wait_flag : boolean;
  375.          wait_str : lstring(10);
  376.          clock_tick : ads of word;
  377.          wait_ticks,start_time : word;
  378.  
  379.      begin
  380.          clock_tick.s := 0;    {address timer in low core}
  381.          clock_tick.r := #46C;
  382.          savescreen;
  383.          xxcls;
  384.          xxmove(0,0);
  385.          write(output,'From IBM file: ');
  386.          readln(input,infile);
  387.          parse_file(infile);
  388.          wait_flag := FALSE;
  389.          assign(ibmfile,infile);
  390.          ibmfile.trap := TRUE; {allow trapping fo errors}
  391.          reset(ibmfile);
  392.          if ibmfile.errs <> 0 then begin
  393.          writeln(chr(7)*'***** File Not Found on Disk *****:',infile);
  394.          sleep(2);
  395.          restorescreen;
  396.          return;
  397.          end;
  398.          write(output,'Clock tick delays between characters (0=>none): ');
  399.          readln(input,wait_ticks);
  400.          if wait_ticks > 0 then wait_flag := TRUE;
  401.  10:
  402. {$mathck-}
  403.          while not eof(ibmfile) do begin
  404.          inchar := ibmfile^;
  405.          if inchar = TEXT_EOF then break;
  406.          send(inchar);
  407.          putchar(inchar);  {echo to screen}
  408.          if xxinkey(inchar) <> 0 then break;
  409.          if wait_flag then begin
  410.              start_time := clock_tick^;
  411.              while (clock_tick^-start_time) < wait_ticks do;
  412.              end;
  413.          get(ibmfile);
  414.          end;
  415. {$mathck+}
  416.          writeln(output,chr(7)*'*** Dump Complete ***');
  417.          close(ibmfile);
  418.          restorescreen;
  419.          end;
  420.  
  421.      function get_x_char(wait_time : word) : integer;
  422.  
  423.      var
  424.          inchar : char;
  425.          start,diff : word;
  426.  
  427.      begin
  428.          start := timer;
  429.          repeat
  430. {$mathck-}
  431.          if not com_get(inchar) then begin
  432.              get_x_char := ord(inchar);
  433.                    {
  434.                  ***DEBUG***write(output,'.',ord(inchar):2:16);}
  435.              return;
  436.              end;
  437.          diff := timer - start;
  438.          until diff > wait_time;
  439.          get_x_char := -1;       {error return}
  440. {$mathck+}
  441.          end;
  442.  
  443.      procedure purge_send(send_char:byte);
  444.  
  445.      var
  446.          send_string : string(1);
  447.  
  448.      begin
  449.          repeat
  450.          until get_x_char(1) < 0;
  451.          send_string[1] := chr(send_char);
  452.          send(send_string);
  453.          end;
  454.  
  455.      procedure xmodem_down_remote(const fn : lstring) [public];
  456.  
  457.      label
  458.          20,30;
  459.  
  460.      const
  461.          X_SOH = wrd(#1);
  462.          X_SOH40 = wrd(#41);
  463.          X_EOT = wrd(#4);
  464.          X_ACK = wrd(#6);
  465.          X_NAK = wrd(#15);
  466.          X_CAN = wrd(#18);
  467.  
  468.      var
  469.          recv_buf : array[1..176] of byte;
  470.          pack_buf : array[1..132] of byte;
  471.          str_ptr : adr of string(128);
  472.          char_cnt : integer;
  473.          err_cnt : integer;
  474.          blk_cnt,msg_len : integer;
  475.          check_sum : word;
  476.          inchar : integer;
  477.          i : integer;
  478.          outfile : lstring(100);
  479.          ibmfile : file of string(128);
  480.          inkey : char;
  481.          old_xon : boolean;
  482.  
  483.      begin
  484.          total_errors := 0;
  485.          savescreen;
  486.          xxcls;
  487.          xxmove(0,0);
  488.          write(output,'File for XMODEM Receive: ');
  489.          if (fn.len = 0) then readln(input,outfile)
  490.          else begin
  491.          copylst(fn, outfile);
  492.          writeln(outfile);
  493.          end;
  494.          parse_file(outfile);
  495.          assign(ibmfile,outfile);
  496.          ibmfile.trap := true;
  497.          rewrite(ibmfile);
  498.          if ibmfile.errs<>0 then begin
  499.          writeln(output,chr(7)*'File not found'*chr(7));
  500.          sleep(2);
  501.          restorescreen;
  502.          return;
  503.          end;
  504.          old_xon := x_cont(false);
  505.                    {turn off the xon/xoff}
  506.          err_cnt := 0;
  507.          blk_cnt := 1;
  508.          str_ptr := adr recv_buf[4];
  509.          purge_send(X_NAK);
  510.          writeln(output,'Hit "Esc" key OR "^X" to terminate RECEIVE');
  511.          sleep(1);
  512.          cursor_off;
  513.          xxcls;
  514.          xxmove(0,0);
  515.          writeln('File: ',outfile);
  516.  30:
  517.          while TRUE do begin
  518.          if xxinkey(inkey) <> 0 then 
  519.  
  520.              if ((inkey = chr(27)) or (inkey = chr(24))) then begin
  521.                    {User typed ESCAPE}
  522.              purge_send(X_CAN);
  523.              writeln(output,'User cancelled receive');
  524.              sleep(2);
  525.              cursor_on;
  526.              restorescreen;
  527.              eval(x_cont(old_xon));
  528.              return;
  529.              end   ;
  530.          char_cnt := 0;
  531.          inchar := get_x_char(10);
  532.          if inchar < 0 then begin
  533.              writeln(output,'Timeout on block #',blk_cnt);
  534.              goto 20;  {count up the errors}
  535.              end;
  536.          if not(wrd(inchar) in [X_SOH,X_SOH40,X_EOT,X_CAN]) then begin
  537.              writeln(output,'Header not correct. ',inchar:2:16);
  538.              goto 20;  {count up the errors}
  539.              end;
  540.          if wrd(inchar) = X_SOH40 then msg_len := 176
  541.          else msg_len := 132;
  542.          char_cnt := char_cnt+1;
  543.          recv_buf[char_cnt] := wrd(inchar);
  544.          repeat
  545.              inchar := get_x_char(1);
  546.              if inchar<0 then begin
  547.              if char_cnt = 1 then break;
  548.                    {EOT are sometimes sent as single characters}
  549.              writeln(output,'Short block #',blk_cnt,char_cnt);
  550.  20:
  551.              err_cnt := err_cnt+1;
  552.              if err_cnt>12 then begin
  553.                  writeln(output,'Receive cancelled due to errors');
  554.                  purge_send(X_CAN);
  555.                  sleep(2);
  556.                  restorescreen;
  557.                  cursor_on;
  558.                  eval(x_cont(old_xon));
  559.                  return;
  560.                  end;
  561.              purge_send(X_NAK);
  562.              cycle 30;
  563.              end;
  564.              char_cnt := char_cnt+1;
  565.              recv_buf[char_cnt] := wrd(inchar);
  566.              until char_cnt >= msg_len;
  567.          if recv_buf[1] = X_CAN then begin
  568.              writeln(output,'Transmitter cancelled');
  569.              sleep(2);
  570.              restorescreen;
  571.              cursor_on;
  572.              eval(x_cont(old_xon));
  573.              return;
  574.              end;
  575.          if recv_buf[1] = X_EOT then begin
  576.              writeln(output,chr(7)*'Received verified'*chr(7));
  577.              close(ibmfile);
  578.              send(chr(X_ACK));
  579.              sleep(2);
  580.              restorescreen;
  581.              cursor_on;
  582.              eval(x_cont(old_xon));
  583.              return;
  584.              end;
  585.          if msg_len = 176 then begin
  586.                    {data from NET/1 -- pack it}
  587.              net_pack(adr recv_buf[1],adr pack_buf[1],132);
  588.              for i := 1 to 132 do recv_buf[i] := pack_buf[i];
  589.              end;
  590.          if (recv_buf[2] xor recv_buf[3])<>#FF then begin
  591.              writeln(output,'Header error block #',blk_cnt, recv_buf[2]:
  592.                  2:16, recv_buf[3]:2:16);
  593.              goto 20;
  594.              end;
  595.          if recv_buf[2] = wrd((blk_cnt-1) and #FF) then begin
  596.              send(chr(X_ACK));
  597.              writeln(output,'Duplicate blocks #',blk_cnt);
  598.              cycle;
  599.              end;
  600.          if recv_buf[2] <> wrd(blk_cnt and #FF) then begin
  601.              writeln(output,'Block count not correct. Expecting',blk_cnt
  602.                  and #FF, ' and got',ord(recv_buf[2]));
  603.              goto 20;
  604.              end;
  605.          check_sum := 0;
  606.          for i := 1 to 128 do check_sum := check_sum + recv_buf[i+3];
  607.          if (check_sum and #FF) <> recv_buf[132] then begin
  608.              writeln(output,'Checksum error block #',blk_cnt,check_sum
  609.                  and #FF, recv_buf[132]);
  610.              goto 20;
  611.              end;
  612.          send(chr(X_ACK));
  613.          ibmfile^ := str_ptr^;
  614.          put(ibmfile);
  615.          disp_data(blk_cnt, err_cnt);
  616.          blk_cnt := blk_cnt+1;
  617.          err_cnt := 0;
  618.          end;
  619.          end;
  620.  
  621.      procedure xmodem_down [public];
  622.  
  623.      var
  624.          l : lstring(2);
  625.  
  626.      begin
  627.          l.len := 0;
  628.          xmodem_down_remote(l);
  629.          end;
  630.  
  631.      procedure xmodem_up_remote(const fn : lstring) [public];
  632.  
  633.      const
  634.          soh = #01;
  635.          eot = #04;
  636.          ack = #06;
  637.          nak = #15;
  638.          can = #18;
  639.  
  640.      var
  641.          i,j : integer;
  642.          ch : string(1);
  643.          blocknum : word;
  644.          numread : integer;
  645.          cksum : integer;
  646.          net_line : boolean;
  647.          inch : char;
  648.          fp : file of string(128);
  649.          name : lstring(60);
  650.          blockbuf : lstring(132);
  651.          unpack_buf : lstring(176);
  652.          last_block : boolean;
  653.          length,nread : integer;
  654.          errors : integer;
  655.          old_xon : boolean;
  656.  
  657.      procedure do_send(c : word);
  658.  
  659.          var
  660.          s : string(1);
  661.  
  662.          begin
  663.          s[1] := chr(c);
  664.          send(s);
  665.          end;
  666.  
  667.      procedure clear_iq;
  668.  
  669.          var
  670.          j : integer;
  671.  
  672.          begin
  673.          repeat
  674.              j := get_x_char(2);
  675.              until j = -1;
  676.          end;
  677.  
  678.      procedure read_in;
  679.  
  680.          var
  681.          ii : integer;
  682.          c : byte;
  683.  
  684.          begin
  685.          copylst(fp^,blockbuf);
  686.          insert('...',blockbuf,1);
  687.          get(fp);
  688.          if eof(fp) then last_block := true;
  689.          end;
  690.  
  691.      begin
  692.          savescreen;
  693.          last_block := false;
  694.          total_errors := 0;
  695.          errors := 0;
  696.          xxcls;
  697.          xxmove(0,0);
  698.          old_xon := x_cont(false);
  699.                    {turn off XON/XOFF}
  700.          write('File name for XMODEM transmit: ');
  701.          if (fn.len = 0) then readln(name)
  702.          else begin
  703.          copylst(fn, name);
  704.          writeln(name);
  705.          end;
  706.          if name[1] = '&' then begin
  707.          net_line := true;
  708.          delete(name,1,1);
  709.          end
  710.          else net_line := false;
  711.          parse_file(name);
  712.          assign(fp, name);
  713.          fp.trap := TRUE;       {catch non-existent file}
  714.          fp.mode := DIRECT;
  715.          reset(fp);
  716.          if fp.errs<>0 then begin
  717.          purge_send(wrd(can));
  718.                    {terminate XMODEM}
  719.          writeln('Non-existent file - ',name);
  720.          sleep(2);
  721.          restorescreen;
  722.          eval(x_cont(old_xon));
  723.          return;
  724.          end;
  725.          length := ord(fp.dosf.z2 * 512 + fp.dosf.z1 div 128);
  726.          if (fp.dosf.z1 and #7F) <> 0 then length := length + 1;
  727.          nread := length;
  728.          writeln('File length is ',length:4,' blocks');
  729.          writeln('Ready for transmission.......');
  730.          writeln('Type ^X to exit..............');
  731.          blocknum := 1;
  732.          i := get_x_char(60);
  733.          if ((i = -1) or (i <> nak) or (xxinkey(inch) >0)) then begin
  734.          writeln('Did not get a startup NAK, got a', i);
  735.          purge_send(wrd(can));
  736.          eval(x_cont(old_xon));
  737.          return;
  738.          end;
  739.          xxcls;
  740.          cursor_off;
  741.          xxmove(0,0);
  742.          writeln('File name: ',name);
  743.          writeln('Total blocks: ',length);
  744.          read_in;
  745.          while (true) do begin
  746.          if (xxinkey(inch) = 1) then
  747.            if inch = Ctrl_X then begin
  748.              writeln('User cancelled transmit');
  749.              purge_send(wrd(can));
  750.              sleep(2);
  751.              restorescreen;
  752.              cursor_on;
  753.              eval(x_cont(old_xon));
  754.              return;
  755.              end;
  756.          if (errors > 10) then begin
  757.              writeln('Transmit cancelled due to errors');
  758.              purge_send(wrd(can));
  759.              sleep(2);
  760.              restorescreen;
  761.              cursor_on;
  762.              eval(x_cont(old_xon));
  763.              return;
  764.              end;
  765.          blockbuf[1] := chr(soh);
  766.          blockbuf[2] := chr(blocknum and #FF);
  767.          blockbuf[3] := chr((not blocknum) and #FF);
  768.          cksum := 0;
  769.          for i := 1 to 128 do begin
  770.              cksum := cksum + ord(blockbuf[i+3]);
  771.              end;
  772.          blockbuf[132] := chr(cksum and #FF);
  773.          blockbuf[0] := chr(132);
  774.          if net_line then begin
  775.              net_unpack(adr blockbuf[1],adr unpack_buf[1],176);
  776.              unpack_buf[0] := chr(176);
  777.              send(unpack_buf);
  778.              end
  779.          else send(blockbuf);
  780.          j := get_x_char(15);
  781.          if (j = nak) then begin
  782.              writeln('got a nak on block', blocknum);
  783.                    { clear_iq; }
  784.              errors := errors + 1;
  785.              cycle;
  786.              end;
  787.          if (j = can) then begin
  788.              writeln('got a can on block', blocknum);
  789.              sleep(2);
  790.              restorescreen;
  791.              cursor_on;
  792.              eval(x_cont(old_xon));
  793.              return;
  794.              end;
  795.          if ((j >= 0) and (j <> ack)) then begin
  796.              writeln('got a strange response(',j,') on block', blocknum)
  797.                  ;
  798.              clear_iq;
  799.              errors := errors + 1;
  800.              cycle;
  801.              end;
  802.          if (j = -1) then begin
  803.              writeln('Timeout on block', blocknum);
  804.              errors := errors + 1;
  805.              cycle;
  806.              end;
  807.          disp_data(ord(blocknum), errors);
  808.          if           {(last_block = true) or}
  809.              (blocknum = wrd(length)) then break;
  810.          read_in;
  811.          blocknum := blocknum + 1;
  812.          errors := 0;
  813.          end;
  814.          while (true) do begin
  815.          if (xxinkey(inch) = 1) then
  816.            if inch = Ctrl_X then begin
  817.              writeln('User cancelled receive');
  818.              purge_send(wrd(can));
  819.              sleep(2);
  820.              restorescreen;
  821.              cursor_on;
  822.              eval(x_cont(old_xon));
  823.              return;
  824.              end;
  825.          do_send(eot);
  826.          j := get_x_char(10);
  827.          if (j = nak) then begin
  828.              writeln('got a nak on EOT');
  829.                    {  clear_iq;  }
  830.              errors := errors + 1;
  831.              cycle;
  832.              end;
  833.          if (j = can) then begin
  834.              writeln('got a can on EOT');
  835.              sleep(2);
  836.              restorescreen;
  837.              cursor_on;
  838.              eval(x_cont(old_xon));
  839.              return;
  840.              end;
  841.          if ((j >= 0) and (j <> ack)) then begin
  842.              writeln('got a strange response on EOT');
  843.              clear_iq;
  844.              cycle;
  845.              end;
  846.          if (j = -1) then begin
  847.              writeln('Timeout on EOT');
  848.              cycle;
  849.              end;
  850.          writeln(chr(7)*'Acknowledged EOT'*chr(7));
  851.          break;
  852.          end;
  853.          sleep(2);
  854.          restorescreen;
  855.          cursor_on;
  856.          eval(x_cont(old_xon));
  857.          end;
  858.  
  859.      procedure xmodem_up [public];
  860.  
  861.      var
  862.          l : lstring(2);
  863.  
  864.      begin
  865.          l.len := 0;
  866.          xmodem_up_remote(l);
  867.          end;   end.
  868.